package smallfrench.moteur.biblio;

import java.util.List;

import smallfrench.moteur.biblio.err.ErreurIndex;
import smallfrench.moteur.interp.RObjet;
import smallfrench.moteur.interp.err.RException;


public abstract class AListeStandard extends AListe {

	public static final AClasse CLASSE = AClasse.creer(
			AListeStandard.class, "ListeStandard");

	final List<RObjet> liste;

	/**
	 * /!\ pas de copie
	 * @param a
	 */
	public AListeStandard(List<RObjet> a) {
		liste = a;
	}

	@Override
	@AnnotationMembre
	public void ajouter(RObjet nouveau) {
		liste.add(nouveau);
	}

	@Override
	@AnnotationMembre
	public RChaine enChaine() {
		StringBuilder sb = new StringBuilder();
		sb.append('(');
		boolean premier = true;
		for (RObjet i : liste) {
			if (premier) {
				premier = false;
			} else {
				sb.append(" ; ");
			}
			sb.append(i);
		}
		return new RChaine(sb.append(')').toString());
	}

	public RObjet[] enTableauJava() {
		return liste.toArray(new RObjet[liste.size()]);
	}

	@Override
	public final boolean equals(Object o) {
		if (o instanceof AListeStandard) {
			AListeStandard autre = (AListeStandard) o;
			return autre.liste.equals(liste);
		}
		return false;
	}

	@Override
	@AnnotationMembre
	public REntier indexDe(RObjet cible) {
		return new REntier(liste.indexOf(cible));
	}

	@Override
	@AnnotationMembre
	public void inserer(REntier index, RObjet nouveau) {
		int i = index.getValeurInt();
		if (i < 0 || i > liste.size())
			throw ErreurIndex.nouvelleException(index);
		liste.add(i, nouveau);
	}

	@Override
	@AnnotationMembre
	public AIterateur iterateur() {
		return new AIterateur.AIterateurStandard(liste.iterator());
	}

	@Override
	@AnnotationMembre
	public RObjet modifier(REntier index, RObjet nouveau) {
		int i = index.getValeurInt();
		if (i < 0 || i >= liste.size())
			throw ErreurIndex.nouvelleException(index);
		return liste.set(i, nouveau);
	}

	@Override
	@AnnotationMembre
	public RObjet obtenir(REntier index) {
		int i = index.getValeurInt();
		if (i >= 0 && i < liste.size())
			return liste.get(i);
		else
			throw ErreurIndex.nouvelleException(index);
	}

	@Override
	public RObjet operateurAssignationIndexBase(RObjet index, RObjet autre) {
		if (index instanceof REntier) {
			REntier a = (REntier) index;
			int i = a.getValeurInt();
			if (i < 0 || i >= liste.size()) {
				throw ErreurIndex.nouvelleException(index);
			}
			liste.set(i, autre);
			return RRien.RIEN;
		}
		return null;
	}

	@Override
	public RObjet operateurEgalBase(RObjet autre) throws RException {
		if (autre instanceof AListeStandard) {
			AListeStandard a = (AListeStandard) autre;
			return RBooleen.nouveau(a.liste.equals(liste));
		}
		return null;
	}

	@Override
	public RObjet operateurIndexBase(RObjet autre) throws RException {
		if (autre instanceof REntier)
			return obtenir((REntier) autre);
		return null;
	}

	@Override
	public RObjet operateurInegalBase(RObjet autre) throws RException {
		if (autre instanceof AListeStandard) {
			AListeStandard a = (AListeStandard) autre;
			return RBooleen.nouveau(! a.liste.equals(liste));
		}
		return null;
	}

	@Override
	@AnnotationMembre
	public RObjet retirer(REntier index) {
		return liste.remove(index.getValeurInt());
	}

	@Override
	@AnnotationMembre
	public REntier taille() {
		return new REntier(liste.size());
	}

}
